// PropVariantConversions.cpp

#include "StdAfx.h"

#include "Common/String/StringConvert.h"

#include "Common/System/Defs.h"

#include "DataConversions.h"

namespace Common
{
namespace String
{

static CString ConvertUInt64ToString(UINT64 value)
{
  TCHAR buffer[32];
  _ui64tot(value, buffer, 10);
  return buffer;
}

static CString ConvertInt64ToString(INT64 value)
{
  TCHAR buffer[32];
  _i64tot(value, buffer, 10);
  return buffer;
}


CString ConvertFileTimeToString(const FILETIME &ft, LCID locale, bool includeTime, bool includeSeconds)
{
  CString result;
  SYSTEMTIME st = {0};
  if (!FileTimeToSystemTime(&ft, &st))
    return _T("");

  if (-1 == locale)
  {
	  locale = ::GetThreadLocale();
  }
  int nDateLength = ::GetDateFormat(locale, DATE_SHORTDATE, &st, NULL, result.GetBuffer(MAX_PATH), MAX_PATH);
  int nPathRemaining = MAX_PATH - nDateLength;
  if(0 == nDateLength)
	  return _T("");
  
  if(0 >= nPathRemaining)
  {
	  nDateLength = ::GetDateFormat(locale, DATE_SHORTDATE, &st, NULL, result.GetBuffer(nDateLength), nDateLength);
  }

  if(includeTime)
  {	  
	  DWORD dwFlags(0);
	  if (!includeSeconds)
	  {
		  dwFlags |= TIME_NOSECONDS;
	  }
	  int nTimeLength = ::GetTimeFormat(locale, dwFlags, &st, NULL, NULL, 0);
	  if(0 == nTimeLength)
	  {
		return result;
	  }
	  //Add one char for one space
	  nTimeLength++;
	  //calculate new string length
	  if (0 >= nPathRemaining - nTimeLength)
	  {
		  nPathRemaining += nPathRemaining - nTimeLength;
	  }
	  	  
	  TCHAR * pBuffer = result.GetBuffer(nDateLength + nPathRemaining);
	  
	  pBuffer[nDateLength -1] = _T(' ');
	  pBuffer += nDateLength;
	  ::GetTimeFormat(locale, dwFlags, &st, NULL, pBuffer, nPathRemaining);
  }

  
  return result;
}
 

CString ConvertPropVariantToString(const PROPVARIANT &prop)
{
  switch (prop.vt)
  {
    case VT_EMPTY: return CString();
    case VT_BSTR: return prop.bstrVal;
    case VT_UI1: return ConvertUInt64ToString(prop.bVal);
    case VT_UI2: return ConvertUInt64ToString(prop.uiVal);
    case VT_UI4: return ConvertUInt64ToString(prop.ulVal);
    case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart);
    case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, -1, true, true);
    // case VT_I1: return ConvertInt64ToString(prop.cVal);
    case VT_I2: return ConvertInt64ToString(prop.iVal);
    case VT_I4: return ConvertInt64ToString(prop.lVal);
    case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart);
    case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-";
    default: throw 150245;
  }
}

UINT64 ConvertPropVariantToUInt64(const PROPVARIANT &prop)
{
  switch (prop.vt)
  {
    case VT_UI1: return prop.bVal;
    case VT_UI2: return prop.uiVal;
    case VT_UI4: return prop.ulVal;
    case VT_UI8: return (UINT64)prop.uhVal.QuadPart;
    default: throw 151199;
  }
}

CString ConvertSizeToString(UINT64 value, bool humanReadable)
{
	
	TCHAR result[MAX_PATH];			

	if (humanReadable)
	{
		if(NULL != ::StrFormatByteSize64 (value, result, MAX_PATH))
		{
			return result;
		}	
	}
	
	_ui64tot(value, result, 10);
		
	//Get bytes word

	CString bytes;
	if(NULL != ::StrFormatByteSize64 (0, bytes.GetBuffer(32), 32))
	{
		bytes.ReleaseBuffer();
		bytes.Replace(_T("0"), result);
			return bytes;
	}
	  
	return result;
}

}
}